<template>
  <div style="margin-top: 10px">
    <!-- <transition-group name="list-complete"> -->
    <div key="search" class="list-complete-item" v-show="isSearchDisplay">
      <the-form
        ref="searchForm"
        v-model="searchData"
        :option="searchOption"
        @reset="searchReset"
        @change="searchChange"
        @submit="searchSubmit"
        v-on="groupListeners.search"
      ></the-form>
      <!-- <the-form
        ref="searchForm"
          v-model="searchData"
          :option="searchOption"
          @submit="searchSubmit"
          @reset="searchReset"
          @change="searchChange"
        ></the-form>-->
    </div>

    <div key="headerMenu" class="header-menu list-complete-item">
      <div style="float: left">
        <el-button
          v-if="
            permission.includes(1) &&
            oc(option, 'headerMenu.isAddBtn') !== false
          "
          type="primary"
          size="mini"
          icon="el-icon-circle-plus-outline"
          @click="addMenu"
          >新增</el-button
        >
        <el-button
          v-if="
            permission.includes(5) &&
            oc(option, 'headerMenu.isExportBtn') !== false
          "
          type="primary"
          size="mini"
          icon="el-icon-download"
          @click="exportXlsx"
          >导出表格</el-button
        >
      </div>
      <div style="float: left; margin-left: 10px">
        <slot name="headerMenuLeft"></slot>
      </div>

      <div style="float: right">
        <el-button
          v-if="oc(option, 'headerMenu.isRefreshBtn') !== false"
          ref="refresh"
          size="mini"
          circle
          icon="el-icon-refresh"
          @click="refreshBtn"
        ></el-button>
        <el-button
          v-if="oc(option, 'headerMenu.isSearchBtn') !== false"
          size="mini"
          circle
          icon="el-icon-search"
          @click="searchBtnClick"
        ></el-button>
        <slot name="headerMenuRight"></slot>
      </div>
      <div style="clear: both"></div>
    </div>

    <!--     
    <el-alert
      v-if="oc(option,'table.selectionColumn.alert') !== false"
      style="margin:6px 0;"
      type="success"
      :closable="false"
    >
      <template #title>
        当前选中 {{selectedList.length}} 项
        <el-button style="padding:2px;color:#67C23A;" type="text" @click="clearSelected">清空</el-button>
      </template>
      </el-alert>-->

    <el-tag
      key="tableTag"
      class="list-complete-item"
      style="width: 100%; margin-bottom: 3px"
      size="medium"
      v-if="oc(option, 'table.selectionColumn.display') !== false"
    >
      当前选中 {{ selectedList.length }} 项
      <el-button style="padding: 0px" type="text" @click="clearSelected"
        >清空</el-button
      >
    </el-tag>

    <!--  -->
    <el-table
      ref="table"
      key="table"
      class="list-complete-item"
      style="width: 100%; overflow-x: scroll"
      :data="tableData"
      :fit="oc(option, 'table.fit') !== false"
      :height="oc(option, 'table.height') || 'auto'"
      :stripe="oc(option, 'table.stripe') === true"
      :border="oc(option, 'table.border') !== false"
      :highlight-current-row="oc(option, 'table.highlight')"
      :header-row-class-name="
        oc(option, 'table.headerRowClassName') || 'tableHeader'
      "
      :empty-text="oc(option, 'table.emptyText') || '暂无数据'"
      v-loading="tableLoading"
      @selection-change="selectionChange"
      @cell-click="cellClick"
      @row-click="rowClick"
      @row-dblclick="rowDblclick"
    >
      <!-- 选择列 -->
      <el-table-column
        v-if="oc(option, 'table.selectionColumn.display') !== false"
        header-align="center"
        align="center"
        prop="prop"
        type="selection"
        label
      ></el-table-column>
      <!-- index列 -->
      <el-table-column
        v-if="oc(option, 'table.indexColumn.display')"
        header-align="center"
        align="center"
        type="index"
        :index="oc(option, 'table.indexColumn.index') || 1"
        prop="prop"
        :label="oc(option, 'table.indexColumn.indexLabel') || '序号'"
      ></el-table-column>

      <!-- 主列 -->
      <el-table-column
        v-for="(colItem, index) in c_option['columns']"
        :key="index"
        :prop="colItem.prop"
        :label="colItem.label"
        :width="colItem.width"
        :header-align="
          colItem.headerAlign || oc(option, 'table.align') || 'left'
        "
        :align="colItem.align || oc(option, 'table.align') || 'left'"
        :show-overflow-tooltip="colItem.overflow"
        :sortable="colItem.sortable"
      >
        <template #default="scope">
          <span v-if="oc(colItem, 'slot')">
            <slot
              :name="colItem.prop + '-col'"
              :scope="scope"
              :col="colItem"
            ></slot>
          </span>
          <span
            v-else-if="colItem.copy"
            v-clipboard.self="cellValueFormat(colItem, scope)"
            >{{ cellValueFormat(colItem, scope) }}</span
          >
          <span v-else>{{ cellValueFormat(colItem, scope) }}</span>
        </template>
      </el-table-column>

      <!-- 表格的操作菜单列 -->
      <el-table-column
        v-if="oc(option, 'table.rowMenuColumn.display') !== false"
        prop="rowMenu"
        header-align="center"
        :align="
          oc(option, 'table.rowMenuColumn.align') ||
          oc(option, 'table.align') ||
          'left'
        "
        :width="oc(option, 'table.rowMenuColumn.width') || ''"
        :label="oc(option, 'table.rowMenuColumn.label') || '操作'"
        :fixed="oc(option, 'table.rowMenuColumn.fixed') || false"
      >
        <template #default="scope">
          <div v-if="oc(option, 'table.rowMenuColumn.slot')">
            <slot name="rowMenu" :data="scope"></slot>
          </div>
          <el-dropdown
            v-else-if="oc(option, 'table.rowMenuColumn.type') === 'dropdown'"
            split-button
            size="small"
            type="primary"
            @click="editRow(scope)"
            @command="tableRowMenuDropdownCommand(scope, $event)"
            trigger="hover"
            placement="bottom-end"
          >
            {{ c_dropdown_editText }}
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item
                icon="el-icon-edit-outline"
                command="edit"
                :disabled="!permission.includes(2)"
                v-if="oc(option, 'table.rowMenuColumn.isEditBtn') !== false"
                >{{ c_dropdown_editText }}</el-dropdown-item
              >
              <el-dropdown-item
                icon="el-icon-view"
                command="view"
                :disabled="!permission.includes(3)"
                v-if="oc(option, 'table.rowMenuColumn.isViewBtn') !== false"
                >查看</el-dropdown-item
              >
              <el-dropdown-item
                icon="el-icon-delete"
                command="del"
                :disabled="!permission.includes(4)"
                v-if="oc(option, 'table.rowMenuColumn.isDelBtn') !== false"
                >删除</el-dropdown-item
              >
              <!-- 注意如果在下拉菜单添加插槽更多按钮，需用el-dropdown-item包裹 -->
              <slot name="rowMenuBtn" :data="scope"></slot>
            </el-dropdown-menu>
          </el-dropdown>

          <div v-else>
            <el-button
              v-if="
                permission.includes(2) &&
                oc(option, 'table.rowMenuColumn.isEditBtn') !== false
              "
              type="primary"
              plain
              size="mini"
              circle
              icon="el-icon-edit"
              @click="editRow(scope)"
            ></el-button>
            <el-button
              v-if="
                permission.includes(3) &&
                oc(option, 'table.rowMenuColumn.isViewBtn') !== false
              "
              type="primary"
              plain
              size="mini"
              circle
              icon="el-icon-view"
              @click="viewRow(scope)"
            ></el-button>
            <el-button
              v-if="
                permission.includes(4) &&
                oc(option, 'table.rowMenuColumn.isDelBtn') !== false
              "
              type="primary"
              plain
              size="mini"
              circle
              icon="el-icon-delete"
              @click="delRow(scope)"
            ></el-button>
            <slot name="rowMenuBtn" :data="scope"></slot>
          </div>
        </template>
      </el-table-column>

      <template #empty>
        <img
          src=""
          alt
        />
        <span style="display: block; line-height: 2px">暂无数据</span>
      </template>
    </el-table>
    <!-- 分页 -->
    <footer key="footer" class="list-complete-item" style="margin-top: 4px">
      <div style="float: left">
        <slot name="footerMenu"></slot>
      </div>
      <div class="text-right">
        <el-pagination
          v-if="oc(option, 'table.pagination') !== false"
          background
          layout="total,sizes,prev,pager,next,jumper"
          :total="page.total"
          :current-page.sync="currentPage"
          :page-size.sync="pageSize"
          :page-sizes="[10, 20, 30, 50, 100, 200]"
          @current-change="currentChange"
          @size-change="sizeChange"
        ></el-pagination>
      </div>
    </footer>
    <!-- 分页/ -->
    <!-- </transition-group> -->
    <!-- dialog 提供查看、编辑row、添加数据的表单，表单结构由option.form配置 -->
    <el-dialog
      :visible.sync="dialogVisible"
      :width="oc(option, 'form.dialogWidth') || '60%'"
      :before-close="dialogBeforeClose"
      :fullscreen="dialogFullscreen"
      :close-on-click-modal="true"
      @open="onDialogOpen"
      top="6vh"
    >
      <template #title>
        <span style="color: #303133">{{ c_dialogTitle }}</span>
        <i
          class="el-icon-full-screen dialog-full-screen"
          @click="dialogFullscreen = !dialogFullscreen"
        ></i>
      </template>
      <div v-if="oc(option, 'form.custom') === 'slot'">
        <slot name="form"></slot>
      </div>
      <div v-else>
        <!-- <div>{{currentRow}}</div> -->
        <!-- :option="{...option.form,items:c_option['formItem']}" -->
        <the-form
          ref="dialogForm"
          :option="theFormOption"
          v-model="formData"
          @submit="formSubmit"
          @change="formChange"
          @reset="dialogFormReset"
        >
          <!--  v-for="item22 in c_option['formSlots']" -->
          <!-- 表单component的组件的slot传入进来 -->
          <template v-for="item22 in c_option['formSlots']" v-slot:[item22]>
            <slot :name="`form-${item22}`"></slot>
          </template>

          <!-- form组件兜底的完全slot传入进去 外部使用form-propName传入slot -->
          <template v-for="item33 in c_option['formSlots2']" v-slot:[item33]>
            <slot :name="`form-${item33}`"></slot>
          </template>
          <template #menu>
            <el-button
              v-if="oc(option, 'form.dialogCloseBtn') !== false"
              type
              plain
              @click="dialogVisible = false"
              icon="el-icon-circle-close"
              size="small"
              >关 闭</el-button
            >
          </template>
        </the-form>
      </div>
      <div slot="footer">
        <slot name="dialogFooter"></slot>
        <!-- <el-button
          v-if="oc(option, 'form.dialogCloseBtn') !== false"
          type
          plain
          @click="dialogVisible = false"
          icon="el-icon-circle-close"
          size="small"
          >关 闭</el-button
        > -->
        <!-- <el-button type="primary" @click="dialogVisible = false">确 定</el-button> -->
      </div>
    </el-dialog>
  </div>
</template>
<script>
import objectMerge from "@/utils/objectMerge";
import objectDeepClone from "@/utils/objectDeepClone";

import theForm from "./BaseForm.vue";

const initMixins = {
  data() {
    return {};
  },
  computed: {
    c_option() {
      const columns = [];
      const formItem = [];
      let formSlots = []; //component传入baseform的组件，需要填充slot的。
      const formSlots2 = []; //slot传入表单baseform的
      if (this.oc(this.option, "table.column")) {
        this.option.table.column.forEach((item, index, cur) => {
          if (item.hiden !== true) columns.push(item);
          const theformItem = this.createFormItem(item);
          // 传入的component表单组件所需的slot
          if (theformItem["componentSlots"]) {
            const a = theformItem["componentSlots"].map(
              (i2) => `${theformItem["prop"]}-${i2}`
            );
            formSlots = [...formSlots, ...a];
          }
          // 自定义的表单组件直接slot进来
          if (theformItem["slot"]) {
            formSlots2.push(theformItem["prop"]);
          }
          if (this.dialogState === 0)
            theformItem.display = theformItem.addDisplay;
          if (this.dialogState === 0)
            theformItem.componentProps.disabled =
              theformItem.addDisabled === true;
          if (this.dialogState === 1)
            theformItem.display = theformItem.editDisplay;
          if (this.dialogState === 1)
            theformItem.componentProps.disabled =
              theformItem.editDisabled === true;
          if (this.dialogState === 2)
            theformItem.display = theformItem.viewDisplay;
          if (this.dialogState === 2)
            theformItem.componentProps.disabled =
              true || theformItem.viewDisabled;
          formItem.push(theformItem);
        });
      }
      // console.log(formSlots);
      return {
        columns, //table展示的列
        formItem,
        formSlots,
        formSlots2,
      };
    },
  },
  methods: {
    createFormItem(item) {
      //接收table的column，根据其中的form选项等返回一个表单组件可用的配置
      let ret = {
        editDisplay: true,
        addDisplay: true,
        viewDisplay: true,
        addDisabled: false,
        editDisabled: false,
        viewDisabled: true,
        display: true,
        label: item.label,
        prop: item.prop,
        component: "el-input",
        span: 12,
        componentProps: {
          disabled: false,
        },
      };
      if (item.form) {
        ret = objectMerge(item.form, ret, true);
      }

      return ret;
    },
    // 如果有options选项，并含有asyncData，则自动执行并通过回调把结果赋值给list
    getAsyncData() {
      this.option.table.column.forEach((item2) => {
        const item = item2.form;
        if (
          item &&
          item.options &&
          item.options.list.length < 1 &&
          item.options.asyncData
        ) {
          item.options.asyncData((data) => {
            item.options.list = data;
          });
        }
      });
    },
  },
  created() {
    this.getAsyncData();
  },
};

const interfaceMixins = {
  methods: {
    /* 提供外部调用，可切换search区域是否隐藏 */
    setSearchDisplay(bol) {
      this.isSearchDisplay = bol;
    },
    setLoading(val) {
      this.setTableLoading(val);
    },
    /* 获取当前表格选中的列表 */
    getSelectedList() {
      return this.selectedList;
    },
    cellClick(row, column, cell, event) {
      this.$emit("cell-click", row, column, cell, event);
    },
    rowClick(row, column, event) {
      this.currentRow = row;
      this.$emit("row-click", row, column, event);
    },
    rowDblclick(row, column, event) {
      this.currentRow = row;
      this.$emit("row-dblclick", row, column, event);
    },
    // 提供外部通过ref调用，打开添加dialog
    openAdd() {
      this.addMenu();
    },
    openEditRow(scope) {
      // 当外部没有传入行scope数据时，就是用内置的。
      this.editRow(scope || { row: this.currentRow });
    },
    openViewRow(scope) {
      this.viewRow(scope || { row: this.currentRow });
    },
    // 提供外部清空表单
    formReset() {
      this.$refs.dialogForm.reset();
    },
    getRefs(ref) {
      return this.$refs[ref];
    },

    getSearchFormRef(ref) {
      return this.$refs.searchForm.getRefs(ref);
    },
    setCurrentRow(row) {
      this.$refs.table.setCurrentRow(row);
    },
    /** 获取dialog form中某个字段的ref。注意应该在首次open过dialog之后才能拿到。 */
    getFormRef(ref) {
      return this.formRef ? this.formRef[ref] : null;
    },
  },
};

const dialogMixins = {
  components: {
    theForm,
  },
  data() {
    return {
      dialogVisible: false,
      dialogFullscreen: false,
      /** dialogState dialog打开类型状态。0新增窗口，1修改窗口，2查看窗口。 */
      dialogState: 0,
      dialogStateList: ["新增", "编辑", "查看"],
      /* 表单v-model */
      formData: {},
      /** 表单备份初始数据 */
      formDataCopy: {},
      /** dialog from的ref */
      formRef: null,
    };
  },
  methods: {
    dialogBeforeClose(done) {
      this.$refs.dialogForm && this.$refs.dialogForm.setLoading(false);
      this.clearValidate(); //打开dialog form时，移除表单校验

      done();
    },
    clearValidate() {
      this.$refs.dialogForm && this.$refs.dialogForm.clearValidate();
    },
    formChange(model, chg, item) {
      this.$emit("input", this.formData);
      this.$emit("form-change", this.formData, chg, item);
    },
    onDialogOpen() {
      this.formRef = this.$refs.dialogForm;
      this.$nextTick(() => {
        this.$emit(
          "dialog-open",
          this.$refs.dialogForm,
          this.dialogState,
          this.currentRow
        );
      });
    },
  },
  computed: {
    c_dialogTitle() {
      return this.dialogStateList[this.dialogState];
    },
    theFormOption() {
      const _default = {
        menu: {
          align: "center",
          resetBtn: {
            display: false,
            disabled: true,
          },
          submitBtn: {
            width: 160,
          },
        },
      };
      const ret = { ...this.option.form, items: this.c_option["formItem"] };

      objectMerge(_default, ret, true, false, true, true);

      // 若打开查看，则隐藏提交按钮
      const menuDisplay = this.dialogState === 2 ? false : true;
      if (ret.menu) {
        ret.menu.display = menuDisplay;
      } else {
        ret.menu = {};
        ret.menu.display = menuDisplay;
      }

      ret.items = ret.items.sort((v1, v2) => {
        v1.index == undefined ? (v1.index = 0) : "";
        v2.index == undefined ? (v2.index = 0) : "";
        return v1.index - v2.index;
      });
      return ret;
    },
  },
  watch: {
    dialogVisible(val) {
      if (val) {
        this.$refs.dialogForm && this.$refs.dialogForm.setLoading(false);
      }
    },
  },
  created() {
    const addTitle = this.oc(this.option, "form.addTitle");
    addTitle && (this.dialogStateList[0] = addTitle);
    const editTitle = this.oc(this.option, "form.editTitle");
    editTitle && (this.dialogStateList[1] = editTitle);
    const viewTitle = this.oc(this.option, "form.viewTitle");
    viewTitle && (this.dialogStateList[2] = viewTitle);
  },
};

const pageMixins = {
  data() {
    return {};
  },
  computed: {
    pageSize: {
      get() {
        return this.page.size || 20;
      },
      set(val) {
        this.$emit("update:page", {
          total: this.page.total,
          size: val,
          currentPage: this.currentPage,
        });
      },
    },
    currentPage: {
      get() {
        return this.page.currentPage || 1;
      },
      set(val) {
        this.$emit("update:page", {
          total: this.page.total,
          size: this.page.size,
          currentPage: val,
        });
      },
    },
  },
  methods: {
    currentChange(currentPage) {
      // console.log(currentPage);
      const arg = {
        currentPage,
        size: this.pageSize,
        offset: this.pageSize * (currentPage - 1),
      };
      this.emitPageChange(arg);
    },
    sizeChange(size) {
      // console.log(size);
      this.$nextTick(() => {
        const arg = {
          currentPage: this.currentPage,
          size: size,
          offset: size * (this.currentPage - 1),
        };
        this.emitPageChange(arg);
      });
    },
    emitPageChange(arg) {
      this.setTableLoading(true);
      this.$emit("page-change", arg, this.setTableLoading);
      // vvv.$emit('page-change',arg, this.setTableLoading)
      this.paginationIndex(arg);
    },
    // 如果index开启了分页模式，则每一页按增量编号，注意index必须配置数字而不是不填了。
    paginationIndex(arg) {
      if (this.oc(this.option, "table.indexColumn.pagination")) {
        this.$nextTick(() => {
          this.option.table.indexColumn.index = (index) =>
            (arg.currentPage - 1) * arg.size + 1 + index;
        });
      }
    },
  },
};

const searchMixins = {
  data() {
    return {
      searchData: {},
      isSearchDisplay: this.oc(this.option, "search.display") !== false,
    };
  },

  computed: {
    searchOption() {
      return this.option.search || {};
    },
  },
  methods: {
    searchSubmit(data, loading) {
      this.$emit("search-submit", this.searchData, loading);
    },
    searchReset(data) {
      this.searchData = data;
      this.$emit("search-reset", data);
    },
    searchChange(data, chg, item) {
      this.$emit("search-change", this.searchData, chg, item);
    },
    searchBtnClick() {
      this.isSearchDisplay = !this.isSearchDisplay;
      this.$emit("search-btn-click", this.isSearchDisplay);
    },
  },
  watch: {
    searchFormModel: {
      deep: true,

      handler(val) {
        this.searchData = this.searchFormModel;
      },
    },
  },
  created() {
    // console.log(this.searchFormModel);
    if (this.searchFormModel) {
      this.searchData = this.searchFormModel;
    }
  },
};

export default {
  name: "base-crud-table",
  mixins: [initMixins, dialogMixins, pageMixins, searchMixins, interfaceMixins],
  props: {
    option: {
      required: true,
      type: Object,
      default() {
        return {};
      },
    },
    data: {
      required: true,
      type: Array,
      default() {
        return [];
      },
    },
    beforeOpenDialog: {
      required: false,
      type: Function,
    },
    page: {
      required: false,
      type: Object,
      default() {
        return {
          total: 0,
          size: 20,
          currentPage: 1,
        };
      },
    },
    loading: {
      required: false,
      type: Boolean,
      default: false,
    },
    searchFormModel: {
      type: Object,
      required: false,
    },
    value: {
      type: Object,
      default() {
        return {};
      },
    },
    permission: {
      type: Array,
      default() {
        return [1, 2, 3, 4, 5];
      },
    },
  },
  data() {
    return {
      // vue:vvv,
      currentRow: {}, //当前行，行的删除、编辑单击双击等时保存

      selectedList: [], //表格选中的列表
      mapDataType: {
        "el-checkbox-group": [],
      },
      groupListeners: {
        search: {},
        page: {},
      },
    };
  },
  methods: {
    /* 对象可选链工具函数 */
    oc(obj, chain) {
      const chainList = chain.split(".");
      // console.log(chainList);
      chainList.some((item) => {
        // console.log(item);
        if (Object.prototype.toString.call(obj[item]) === "[object Boolean]") {
          obj = obj[item];
          return true;
        } else {
          obj = obj[item] || undefined;
          return !obj;
        }
      });
      // console.log(obj);
      return obj;
    },
    // 当某列数据需要映射时，接收一个映射对象，其中label规定显示内容字段，key是数据字段。list是映射集合
    mapObj(map, val) {
      // console.log(arr);
      const arr = map.list;
      // 如果提供filter函数，就用它来决定返回显示值
      if (map.filter) {
        return map.filter(val, arr);
      }
      // 如果list是对象集合
      if (Array.isArray(arr)) {
        const a = arr.find((item) => item[map.valueKey] === val);
        if (a) {
          return a[map.label];
        } else {
          return val;
        }
      } else {
        throw "map.list必须是数组，形如：[{label:'',value:''}]";
      }
    },
    // 每一个单元格渲染的内容的函数处理
    cellValueFormat(colItem, scope) {
      if (this.oc(colItem, "form.options.list")) {
        return this.mapObj(colItem.form.options, scope.row[colItem.prop]);
      } else {
        return scope.row[colItem.prop];
      }
    },
    openDialog(dialogState, callback, editRowScope) {
      // console.log(this.beforeOpenDialog(dialogState));
      if (this.beforeOpenDialog) {
        this.beforeOpenDialog(this.dialogState, callback, editRowScope);
        //  this.beforeOpenDialog(this.dialogStateList[dialogState], resolve);
      } else {
        callback();
      }
    },
    editRow(scope) {
      if (!this.permission.includes(2)) {
        this.$message.error("对不起，您没有权限编辑！");
        return;
      }
      // this.$message.success(scope.toString())
      if (this.oc(this.option, "table.rowMenuColumn.isEditBtn") === false) {
        return;
      }
      this.dialogState = 1;
      this.openDialog(
        this.dialogState,
        () => {
          this.currentRow = scope.row;
          this.formData = objectDeepClone(this.currentRow);
          this.$emit("input", this.formData);

          // console.log(scope);
          this.dialogVisible = true;
        },
        scope
      );
    },
    viewRow(scope) {
      // this.$message.success(scope.toString())
      this.dialogState = 2;
      this.openDialog(this.dialogState, () => {
        this.currentRow = scope.row;
        this.formData = this.currentRow;
        // this.option.form.items.forEach(item => {
        //   // item.disabled = true;
        //   if (item.componentProps) {
        //     this.$set(item.componentProps, "readonly", true);
        //   } else {
        //     this.$set(item, "componentProps", {});
        //     this.$set(item.componentProps, "readonly", true);
        //   }
        // });
        // console.log(scope);
        this.dialogVisible = true;
      });
    },
    delRow(scope) {
      this.$emit("row-del", scope);
    },
    tableRowMenuDropdownCommand(scope, e) {
      // console.log(scope,e);
      if (e === "edit") {
        this.editRow(scope);
      } else if (e === "view") {
        this.viewRow(scope);
      } else if (e === "del") {
        this.delRow(scope);
      }
      this.$emit("row-menu-dropdown", scope, e);
    },
    /* 创建表单数据模型，addMenu时需要 */
    createFormData() {
      // debugger
      if (this.oc(this.option, "table.column")) {
        const ret = {};
        this.option.table.column.forEach((item) => {
          // 读取内置的默认值，主要是规定字段的类型
          const defaultFormData = this.mapDataType[
            this.oc(item, "form.component")
          ];
          // 读取外部的通过vmodel传递的值。实现formdata双绑
          const modelValue =
            this.value[item.prop] !== undefined ? this.value[item.prop] : null;
          let retData = defaultFormData !== undefined ? defaultFormData : null;
          retData = modelValue || retData;
          ret[item.prop] = retData;
        });
        return ret;
      }
      return {};
    },
    addMenu() {
      this.dialogState = 0;
      this.openDialog(this.dialogState, () => {
        // this.formData = {};
        this.formData = this.createFormData();
        this.$emit("input", this.formDataCopy);

        // console.log(this.formData);
        this.clearValidate();
        this.$nextTick(() => {
          // console.log(this.formData);
          this.dialogVisible = true;
        });
      });
    },
    refreshBtn() {
      this.setTableLoading(true);
      this.$emit("refresh", this.setTableLoading);
    },
    setTableLoading(val) {
      this.tableLoading = !!val;
    },

    selectionChange(selection) {
      this.selectedList = selection;
      this.$emit("selection-change", selection);
    },
    clearSelected() {
      this.$refs.table.clearSelection();
    },
    closeDialog() {
      this.dialogVisible = false;
    },
    formSubmit(formData, loading) {
      if (this.dialogState === 0) {
        this.$emit("add-submit", this.formData, loading, this.closeDialog);
      } else if (this.dialogState === 1) {
        this.$emit("row-edit-submit", this.formData, loading, this.closeDialog);
      }
    },
    dialogFormReset(data) {
      this.formData = data;
      this.$emit("form-reset", data);
    },
    /* 导出excel表格 */
    exportXlsx() {
      // console.log(this.tableData);
      let columns = this.option.table.column;
      // let columns = this.c_option["columns"];
      let downloadData =
        this.selectedList.length > 0 ? this.selectedList : this.tableData;
      columns = objectDeepClone(columns);
      columns.unshift({ label: "序号", prop: "index" });
      downloadData = objectDeepClone(downloadData);
      downloadData.forEach((dataItem, index) => {
        columns.forEach((colItem) => {
          if (colItem.prop === "index") {
            dataItem.index = index + 1;
          } else {
            dataItem[colItem.prop] = this.cellValueFormat(colItem, {
              row: dataItem,
            });
          }
        });
      });
      this.$xlsx.export({
        title: this.option.title || "导出表格",
        columns,
        data: downloadData,
      });
    },
    /* 提取分类事件，会挂载在封装对应组件上。 */
    extractEvent() {
      const listeners = this.$listeners;
      // const preNameList = {
      //   search:{},
      //   page:{},
      // };

      Object.keys(listeners).forEach((item) => {
        const strs = item.split("__");
        if (strs.length === 2) {
          this.groupListeners[strs[0]][strs[1]] = listeners[item];
        }
      });
      // console.log(this.groupListeners);
    },
  },
  computed: {
    tableData() {
      return this.data;
    },
    tableLoading: {
      get() {
        return this.loading;
      },
      set(val) {
        this.$emit("update:loading", val);
      },
    },
    c_dropdown_editText() {
      return (
        this.oc(this.option, "table.rowMenuColumn.dropdown.editText") || "编辑"
      );
    },
  },
  components: {},
  watch: {
    value: {
      deep: true,
      immediate: true,
      handler(nv, ov) {
        this.formData = nv;
      },
    },
  },
  created() {
    // console.log(this.$listeners)
    this.extractEvent();
    this.formDataCopy = objectDeepClone(this.value);
  },
  mounted() {},
};
</script>
<style scoped>
.header-menu {
  margin: 10px 0 5px 0;
}
.dialog-full-screen {
  position: absolute;
  top: 21px;
  right: 46px;
  font-size: 14px;
  cursor: pointer;
  color: #909399;
}
.dialog-full-screen:hover {
  color: #409eff;
}
/deep/ .tableHeader th {
  background: #f5f7fa !important;
  /* background: #fafafa !important; */
}

/* .flip-list-move {
  transition: transform 1s;
} */
</style>
<style>
.list-complete-item {
  transition: all 0.6s;
  /* display: inline-block;
  margin-right: 10px; */
}
.list-complete-enter-active,
.list-complete-leave-active {
  transition: all 0.6s;
  /* position: absolute; */
}
.list-complete-enter, .list-complete-leave-to
/* .list-complete-leave-active for below version 2.1.8 */ {
  opacity: 0;
  /* transform: translateY(-10px); */
}
/* .list-complete-enter-to, .list-complete-leave{
   opacity: 1;
  transform: translateY(0px);
} */
/* .list-complete-leave-active {
  position: absolute;
  transition: all 0.6s;
} */
</style>